package city.spring.modules.checkinfeeDetail.service.impl;

import city.spring.modules.bed.service.BedManagementService;
import city.spring.modules.bed.vo.BedInfoVO;
import city.spring.modules.checkinfeeDetail.entity.CheckinfeeDetailEntity;
import city.spring.modules.checkinfeeDetail.repository.CheckinfeeDetailRepository;
import city.spring.modules.checkinfeeDetail.service.CheckinfeeDetailService;
import city.spring.modules.checkinfeeDetail.vo.CheckinfeeDetailVO;
import city.spring.modules.checkinfeeDetail.vo.PrintCheckinfeeVO;
import city.spring.modules.checkinfeeDetail.vo.PrintOldmanDepositVO;
import city.spring.modules.oldman.entity.OldmanInfoEntity;
import city.spring.modules.oldman.service.OldmanInfoService;
import city.spring.modules.oldman.vo.OldmanDepositVO;
import city.spring.utils.UserUtils;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Service：入院收费记录
 *
 * @author 谢金婷
 * @date 2020-08-24 15:46:11
 */
@CacheConfig(cacheNames = {CheckinfeeDetailServiceImpl.CACHE_NAME})
@Transactional(rollbackFor = Exception.class)
@Service
public class CheckinfeeDetailServiceImpl extends ServiceImpl<CheckinfeeDetailRepository, CheckinfeeDetailEntity> implements CheckinfeeDetailService {

    private final BedManagementService bedManagementService;
    private final CheckinfeeDetailRepository checkinfeeDetailRepository;
    @Autowired
    OldmanInfoService oldmanInfoService;

    public CheckinfeeDetailServiceImpl(BedManagementService bedManagementService, CheckinfeeDetailRepository checkinfeeDetailRepository) {
        this.bedManagementService = bedManagementService;
        this.checkinfeeDetailRepository = checkinfeeDetailRepository;
    }

    @Override
    public void saveCheckinfee(CheckinfeeDetailEntity entity) {
        if (!save(entity)) {
            throw new RuntimeException("保存信息失败");
        }
    }

    @Override
    public void updateCheckinfee(CheckinfeeDetailEntity entity) {
        // 使用 updateById(entity); 修改数据时，将会修改 entity 对象中所有非null数据，如果某个字段为null，将会忽略该字段的修改
        if (!updateById(entity)) {
            throw new RuntimeException("修改信息失败");
        }
    }

    @Override
    public void deleteCheckinfee(String primaryKey) {
        removeById(primaryKey);
    }

    @Override
    public void deleteCheckinfee(List<String> primaryKeys) {
        removeByIds(primaryKeys);
    }

    @Override
    public IPage<CheckinfeeDetailVO> listPage(Page<? extends CheckinfeeDetailEntity> page, Wrapper<? extends CheckinfeeDetailEntity> wrapper) {
        return baseMapper.listPage(page, wrapper);
    }

    @Override
    public PrintCheckinfeeVO getPrintReceiptInfo(List<String> ids) {
        List<CheckinfeeDetailEntity> list;
        if (ids.isEmpty()) {
            list = new ArrayList<>();
        } else {
            list = lambdaQuery().in(CheckinfeeDetailEntity::getId, ids).list();
        }
        Set<String> collect = list.stream().map(CheckinfeeDetailEntity::getOldmanId).collect(Collectors.toSet());
        if (collect.size() != 1) {
            throw new RuntimeException("请只选择一个人的消费记录");
        }
        OldmanInfoEntity oldmanInfoEntity = oldmanInfoService.lambdaQuery().eq(OldmanInfoEntity::getId, list.get(0).getOldmanId()).one();
        if (oldmanInfoEntity == null) {
            throw new RuntimeException("找不到该消费记录关联的老人信息");
        }
        // 获得老人的床位信息
        BedInfoVO bedInfoVO = bedManagementService.getOldmanBed(oldmanInfoEntity.getId());
        PrintCheckinfeeVO vo = new PrintCheckinfeeVO();
        vo.setOldmanName(oldmanInfoEntity.getOldmanName());
        vo.setUserName(UserUtils.getUser().getNickname());
        vo.setOldmanBed(bedInfoVO);
        // 生成打印时所需要的打印明细
        List<PrintCheckinfeeVO.PrintCheckinfeeRecordVO> recordVOList = list.stream().map(item -> {
            PrintCheckinfeeVO.PrintCheckinfeeRecordVO recordVO = new PrintCheckinfeeVO.PrintCheckinfeeRecordVO();
            recordVO.setId(item.getId());
            recordVO.setItemId(item.getConsumptionItemsId());
            recordVO.setStandardPrice(item.getStandardPrice());
            recordVO.setReceivableThisMonth(item.getReceivableThisMonth());
            recordVO.setStatus("收费");
            recordVO.setFeetype(item.getFeestatus());
            return recordVO;
        }).collect(Collectors.toList());
        // 记录合计金额
//        BigDecimal bigDecimal = recordVOList.stream().map(PrintReceiptVO.PrintReceiptRecordVO::getAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
//        PrintReceiptVO.PrintReceiptRecordVO recordVO = new PrintReceiptVO.PrintReceiptRecordVO();
//        recordVO.setId("");
//        recordVO.setAmount(bigDecimal);
//        recordVO.setStatus("合计");
//        recordVOList.add(recordVO);
        vo.setList(recordVOList);
        return vo;
    }

    @Override
    public List<CheckinfeeDetailEntity> getFixedcostsByOldmanIdAndMark(String checkinfeeId, String oldmanId, String mark) {
        return checkinfeeDetailRepository.getFixedcostsByOldmanIdAndMark(checkinfeeId, oldmanId, mark);
    }

    @Override
    public List<CheckinfeeDetailEntity> getDepositByOldmanIdAndMark(String checkinfeeId, String oldmanId, String mark) {
        return checkinfeeDetailRepository.getDepositByOldmanIdAndMark(checkinfeeId, oldmanId, mark);
    }

    @Override
    public List<CheckinfeeDetailEntity> getMfeeByOldmanIdAndMark(String checkinfeeId, String oldmanId, String mark) {
        return checkinfeeDetailRepository.getMfeeByOldmanIdAndMark(checkinfeeId, oldmanId, mark);
    }

    @Override
    public BigDecimal getSumReceivablethisMonth(String checkinfeeId, String oldmanId, String mark) {
        return checkinfeeDetailRepository.getSumReceivablethisMonth(checkinfeeId, oldmanId, mark);
    }

    @Override
    public List<CheckinfeeDetailEntity> getDiningfeeByOldmanIdAndMark(String checkinfeeId, String oldmanId, String mark) {
        return checkinfeeDetailRepository.getDiningfeeByOldmanIdAndMark(checkinfeeId, oldmanId, mark);
    }

    @Override
    public List<CheckinfeeDetailEntity> getUtilitybillByOldmanIdAndMark(String checkinfeeId, String oldmanId, String mark) {
        return checkinfeeDetailRepository.getUtilitybillByOldmanIdAndMark(checkinfeeId, oldmanId, mark);
    }

    @Override
    public List<CheckinfeeDetailEntity> getCheckinfeeDetailByOldmanId(String oldmanId) {
        return checkinfeeDetailRepository.getCheckinfeeDetailByOldmanId(oldmanId);
    }

    @Override
    public List<CheckinfeeDetailVO> getDiningfeeByOldmanId(String oldmanId) {
        return checkinfeeDetailRepository.getDiningfeeByOldmanId(oldmanId);
    }

    @Override
    public List<CheckinfeeDetailVO> getUtilitybillByOldmanId(String oldmanId) {
        return checkinfeeDetailRepository.getUtilitybillByOldmanId(oldmanId);
    }

    @Override
    public List<CheckinfeeDetailVO> getDepositByOldmanId(String oldmanId) {
        return checkinfeeDetailRepository.getDepositByOldmanId(oldmanId);
    }

    @Override
    public List<CheckinfeeDetailVO> getFixedcostsByOldmanId(String oldmanId) {
        return checkinfeeDetailRepository.getFixedcostsByOldmanId(oldmanId);
    }

    @Override
    public List<CheckinfeeDetailEntity> getCheckinfeeDetailByCheckinfeeId(String checkinfeeId) {
        return checkinfeeDetailRepository.getCheckinfeeDetailByCheckinfeeId(checkinfeeId);
    }

    @Override
    public CheckinfeeDetailEntity getDiningfee(String oldmanId) {
        return checkinfeeDetailRepository.getDiningfee(oldmanId);
    }

    @Override
    public CheckinfeeDetailEntity getUtilitybill(String oldmanId) {
        return checkinfeeDetailRepository.getUtilitybill(oldmanId);
    }


    @Override
    public List<CheckinfeeDetailVO> monthPayInfo(String checkfeeid) {
        return checkinfeeDetailRepository.monthPayInfo(checkfeeid);
    }

    @Override
    public CheckinfeeDetailVO monthPayInfoOne(String checkfeeid, Integer typenum) {
        return checkinfeeDetailRepository.monthPayInfoOne(checkfeeid, typenum);
    }

    @Override
    public List<CheckinfeeDetailEntity> getMonthlyfee(String oldmanId) {
        return checkinfeeDetailRepository.getMonthlyfee(oldmanId);
    }

    @Override
    public List<CheckinfeeDetailEntity> getMonthlyfeeByOldmanIdAndMark(String checkinfeeId, String oldmanId, String mark) {
        return checkinfeeDetailRepository.getMonthlyfeeByOldmanIdAndMark(checkinfeeId, oldmanId, mark);
    }

    @Override
    public List<CheckinfeeDetailEntity> getMonthlyfeeByOldmanId(String oldmanId) {
        return checkinfeeDetailRepository.getMonthlyfeeByOldmanId(oldmanId);
    }

    @Override
    public CheckinfeeDetailEntity getAttendance(String oldmanId) {
        return checkinfeeDetailRepository.getAttendance(oldmanId);
    }

    @Override
    public CheckinfeeDetailEntity getPrivatecustomizationFee(String oldmanId) {
        return checkinfeeDetailRepository.getPrivatecustomizationFee(oldmanId);

    }

    @Override
    public CheckinfeeDetailEntity getBed(String oldmanId) {
        return checkinfeeDetailRepository.getBed(oldmanId);

    }

    @Override
    public IPage<OldmanDepositVO> oldmanDepositListPage(Page<? extends CheckinfeeDetailEntity> page, Wrapper<? extends CheckinfeeDetailEntity> wrapper) {
        return baseMapper.oldmanDepositListPage(page, wrapper);
    }

    @Override
    public PrintOldmanDepositVO getPrintOldmanDeposit(List<String> ids) {
        List<CheckinfeeDetailEntity> list;
        if (ids.isEmpty()) {
            list = new ArrayList<>();
        } else {
            list = lambdaQuery().in(CheckinfeeDetailEntity::getId, ids).list();
        }
        Set<String> collect = list.stream().map(CheckinfeeDetailEntity::getOldmanId).collect(Collectors.toSet());
        if (collect.size() != 1) {
            throw new RuntimeException("请只选择一个人的押金");
        }
        OldmanInfoEntity oldmanInfoEntity = oldmanInfoService.lambdaQuery().eq(OldmanInfoEntity::getId, list.get(0).getOldmanId()).one();
        if (oldmanInfoEntity == null) {
            throw new RuntimeException("找不到该消费记录关联的老人信息");
        }
        // 押金信息 deposit
        CheckinfeeDetailEntity deposit = checkinfeeDetailRepository.getDeposit(oldmanInfoEntity.getId());
        System.out.println("打印押金 deposit" + deposit);
        // 获得老人的床位信息
        BedInfoVO bedInfoVO = bedManagementService.getOldmanBed(oldmanInfoEntity.getId());
        PrintOldmanDepositVO vo = new PrintOldmanDepositVO();
        vo.setOldmanName(oldmanInfoEntity.getOldmanName());
        vo.setUserName(UserUtils.getUser().getNickname());
        vo.setOldmanBed(bedInfoVO);
        vo.setPayer(deposit.getPayer());

        // 生成打印时所需要的打印明细
        List<PrintOldmanDepositVO.PrintOldmanDepositRecordVO> recordVOList = list.stream().map(item -> {
            PrintOldmanDepositVO.PrintOldmanDepositRecordVO recordVO = new PrintOldmanDepositVO.PrintOldmanDepositRecordVO();
            recordVO.setId(item.getId());
            recordVO.setItemId(item.getConsumptionItemsId());
            recordVO.setItemName(deposit.getName());
            recordVO.setAmount(item.getStandardPrice());
            recordVO.setStatus("收费");
            return recordVO;
        }).collect(Collectors.toList());
        vo.setList(recordVOList);
        return vo;
    }

    @Override
    public List<CheckinfeeDetailVO> monthPayDetail(String feeid) {
        return checkinfeeDetailRepository.monthPayDetail(feeid);
    }

    @Override
    public CheckinfeeDetailVO getDepositAndBalance(String personId) {
        return checkinfeeDetailRepository.getDepositAndBalance(personId);
    }

    @Override
    public List<CheckinfeeDetailVO> billToLeaveDate(String personId, Date leaveDate, Date monthEnd) {
        String A = new SimpleDateFormat("yyyyMMdd").format(leaveDate);
        String B = new SimpleDateFormat("yyyyMMdd").format(monthEnd);
        String leave = new SimpleDateFormat("yyyyMM").format(leaveDate);
        int leaveMonth = Integer.parseInt(leave);
        if (A.equals(B)) {
            return checkinfeeDetailRepository.billToLeaveDateByMonthEnd(personId, leaveMonth);
        } else {
            return checkinfeeDetailRepository.billToLeaveDateByMonthMid(personId, leaveMonth);
        }
    }
}